package list_set

import "sync"

//Set 专用数据结构，效率比较差，用于小量的数据
type Set[T any] struct {
	list []T
	sync.RWMutex
	cmp Comparator[T]
}
type Comparator[T any] func(a, b T) bool

func NewSet[T any](cmp Comparator[T]) *Set[T] {
	return &Set[T]{
		list:    make([]T, 0),
		RWMutex: sync.RWMutex{},
		cmp:     cmp,
	}
}
func (s *Set[T]) find(element T) bool {
	for _, item := range s.list {
		if s.cmp(item, element) {
			return true
		}
	}
	return false
}

//PushN  插入过程中去重
func (s *Set[T]) PushN(elements ...T) {
	s.Lock()
	defer s.Unlock()
	for _, element := range elements {
		if s.find(element) {
			continue
		}
		s.list = append(s.list, element)
	}
}
func (s *Set[T]) Diff(elements ...T) []T {
	s.Lock()
	defer s.Unlock()
	var result = make([]T, 0)
	for _, element := range elements {
		if s.find(element) {
			continue
		}
		s.list = append(s.list, element)
		result = append(result, element)
	}
	return result
}

func (s *Set[T]) PopN(n int) []T {
	s.Lock()
	defer s.Unlock()
	if len(s.list) < n {
		n = len(s.list)
	}
	result := s.list[:n]
	s.list = s.list[n:]
	return result
}

type Visitor[V any] func(value V) bool

// Traversal traversals elements in the set, it will not stop until to the end of the set or the visitor returns false
func (s *Set[T]) Traversal(visitor Visitor[T]) {
	s.RLock()
	defer s.RUnlock()

	for _, item := range s.list {
		if !visitor(item) {
			break
		}
	}
}

func (s *Set[T]) Erase(element T) {
	s.RLock()
	defer s.RUnlock()
	list2 := make([]T, 0)
	for _, item := range s.list {
		if !s.cmp(item, element) {
			list2 = append(list2, item)
		}
	}
	s.list = list2
}

// Size returns the amount of element in the set
func (s *Set[T]) Size() int {
	s.RLock()
	defer s.RUnlock()

	return len(s.list)
}

func (s *Set[T]) ToSlice() []T {
	s.RLock()
	defer s.RUnlock()
	dst := make([]T, len(s.list))
	copy(dst, s.list)
	return s.list
}
